package com.agrimall.service.impl;

import com.agrimall.entity.Order;
import com.agrimall.entity.OrderItem;
import com.agrimall.mapper.OrderItemMapper;
import com.agrimall.mapper.OrderMapper;
import com.agrimall.service.OrderService;
import com.agrimall.service.UserService;
import com.agrimall.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * 订单服务实现类
 */
public class OrderServiceImpl implements OrderService {
    
    /**
     * 生成订单编号
     */
    private String generateOrderNo() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        return "ORD" + sdf.format(new Date()) + (int)(Math.random() * 1000);
    }
    
    @Override
    public String createOrder(Order order, List<OrderItem> orderItems) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try {
            OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
            OrderItemMapper itemMapper = sqlSession.getMapper(OrderItemMapper.class);
            
            // 生成订单编号
            String orderNo = generateOrderNo();
            order.setOrderNo(orderNo);
            order.setStatus(0); // 待付款
            
            // 插入订单
            int result = orderMapper.insert(order);
            if (result > 0) {
                // 插入订单明细
                for (OrderItem item : orderItems) {
                    item.setOrderId(order.getOrderId());
                }
                itemMapper.insertBatch(orderItems);
                sqlSession.commit();
                return orderNo;
            }
            sqlSession.rollback();
            return null;
        } catch (Exception e) {
            sqlSession.rollback();
            e.printStackTrace();
            return null;
        } finally {
            sqlSession.close();
        }
    }
    
    @Override
    public Order getOrderById(Long orderId) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try {
            OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
            OrderItemMapper itemMapper = sqlSession.getMapper(OrderItemMapper.class);
            
            Order order = mapper.selectById(orderId);
            if (order != null) {
                order.setOrderItems(itemMapper.selectByOrderId(orderId));
            }
            return order;
        } finally {
            sqlSession.close();
        }
    }
    
    @Override
    public Order getOrderByOrderNo(String orderNo) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try {
            OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
            OrderItemMapper itemMapper = sqlSession.getMapper(OrderItemMapper.class);
            
            Order order = mapper.selectByOrderNo(orderNo);
            if (order != null) {
                order.setOrderItems(itemMapper.selectByOrderId(order.getOrderId()));
            }
            return order;
        } finally {
            sqlSession.close();
        }
    }
    
    @Override
    public boolean updateOrder(Order order) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try {
            OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
            int result = mapper.update(order);
            sqlSession.commit();
            return result > 0;
        } catch (Exception e) {
            sqlSession.rollback();
            e.printStackTrace();
            return false;
        } finally {
            sqlSession.close();
        }
    }
    
    @Override
    public List<Order> getOrderListByUser(Long userId, int page, int pageSize) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try {
            OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
            int offset = (page - 1) * pageSize;
            return mapper.selectByUserId(userId, offset, pageSize);
        } finally {
            sqlSession.close();
        }
    }
    
    @Override
    public List<Order> getOrderListByMerchant(Long merchantId, int page, int pageSize) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try {
            OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
            int offset = (page - 1) * pageSize;
            return mapper.selectByMerchantId(merchantId, offset, pageSize);
        } finally {
            sqlSession.close();
        }
    }
    
    @Override
    public boolean payOrder(String orderNo, String paymentMethod) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try {
            OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
            Order order = mapper.selectByOrderNo(orderNo);
            if (order == null || order.getStatus() != 0) {
                return false;
            }
            
            // 无论选择微信还是支付宝，都扣减用户余额
            UserService userService = new UserServiceImpl();
            BigDecimal totalAmount = order.getTotalAmount();
            
            // 扣减用户余额
            boolean deductSuccess = userService.deductBalance(order.getUserId(), totalAmount);
            if (!deductSuccess) {
                // 余额不足，支付失败
                return false;
            }
            
            // 余额扣减成功，更新订单状态
            order.setStatus(1); // 待发货
            order.setPaymentMethod(paymentMethod != null ? paymentMethod : "余额支付");
            order.setPaymentTime(new Date());
            int result = mapper.update(order);
            sqlSession.commit();
            return result > 0;
        } catch (Exception e) {
            sqlSession.rollback();
            e.printStackTrace();
            return false;
        } finally {
            sqlSession.close();
        }
    }
    
    @Override
    public boolean shipOrder(Long orderId, String logisticsCompany, String logisticsNo) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try {
            OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
            Order order = mapper.selectById(orderId);
            if (order != null && order.getStatus() == 1) {
                order.setStatus(2); // 待收货
                order.setLogisticsCompany(logisticsCompany);
                order.setLogisticsNo(logisticsNo);
                int result = mapper.update(order);
                sqlSession.commit();
                return result > 0;
            }
            return false;
        } catch (Exception e) {
            sqlSession.rollback();
            e.printStackTrace();
            return false;
        } finally {
            sqlSession.close();
        }
    }
    
    @Override
    public boolean confirmReceipt(Long orderId) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try {
            OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
            Order order = mapper.selectById(orderId);
            if (order != null && order.getStatus() == 2) {
                order.setStatus(3); // 已完成
                int result = mapper.update(order);
                sqlSession.commit();
                return result > 0;
            }
            return false;
        } catch (Exception e) {
            sqlSession.rollback();
            e.printStackTrace();
            return false;
        } finally {
            sqlSession.close();
        }
    }
    
    @Override
    public boolean cancelOrder(Long orderId) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try {
            OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
            Order order = mapper.selectById(orderId);
            // 只允许待发货（状态1）的订单取消
            if (order != null && order.getStatus() == 1) {
                order.setStatus(4); // 已取消
                int result = mapper.update(order);
                sqlSession.commit();
                return result > 0;
            }
            return false;
        } catch (Exception e) {
            sqlSession.rollback();
            e.printStackTrace();
            return false;
        } finally {
            sqlSession.close();
        }
    }
    
    @Override
    public boolean applyAfterSale(Long orderId) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try {
            OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
            Order order = mapper.selectById(orderId);
            // 只允许已完成（状态3）的订单申请售后
            if (order != null && order.getStatus() == 3) {
                order.setStatus(5); // 售后中
                int result = mapper.update(order);
                sqlSession.commit();
                return result > 0;
            }
            return false;
        } catch (Exception e) {
            sqlSession.rollback();
            e.printStackTrace();
            return false;
        } finally {
            sqlSession.close();
        }
    }
    
    @Override
    public int countOrdersByUser(Long userId) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try {
            OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
            return mapper.countByUserId(userId);
        } finally {
            sqlSession.close();
        }
    }
    
    @Override
    public int countOrdersByMerchant(Long merchantId) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try {
            OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
            return mapper.countByMerchantId(merchantId);
        } finally {
            sqlSession.close();
        }
    }
    
    @Override
    public int countAllOrders() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try {
            OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
            return mapper.countAll();
        } finally {
            sqlSession.close();
        }
    }
    
    @Override
    public List<Order> getOrderListForAdmin(int page, int pageSize) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try {
            OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
            int offset = (page - 1) * pageSize;
            return mapper.selectAllForAdmin(offset, pageSize);
        } finally {
            sqlSession.close();
        }
    }
    
    @Override
    public List<Order> searchOrdersForAdmin(String orderNo, Integer status, Long merchantId, Long userId, int page, int pageSize) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try {
            OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
            int offset = (page - 1) * pageSize;
            return mapper.selectForAdminByConditions(orderNo, status, merchantId, userId, offset, pageSize);
        } finally {
            sqlSession.close();
        }
    }
    
    @Override
    public int countOrdersForAdminByConditions(String orderNo, Integer status, Long merchantId, Long userId) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try {
            OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
            return mapper.countForAdminByConditions(orderNo, status, merchantId, userId);
        } finally {
            sqlSession.close();
        }
    }
    
    @Override
    public List<Order> searchOrdersByMerchant(Long merchantId, String orderNo, String receiverName, String receiverPhone, int page, int pageSize) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try {
            OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
            int offset = (page - 1) * pageSize;
            return mapper.selectByMerchantWithConditions(merchantId, orderNo, receiverName, receiverPhone, offset, pageSize);
        } finally {
            sqlSession.close();
        }
    }
    
    @Override
    public int countOrdersByMerchantWithConditions(Long merchantId, String orderNo, String receiverName, String receiverPhone) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try {
            OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
            return mapper.countByMerchantWithConditions(merchantId, orderNo, receiverName, receiverPhone);
        } finally {
            sqlSession.close();
        }
    }
    
    @Override
    public List<Order> searchOrdersForAdminWithAccount(String orderNo, Integer status, String merchantUsername, String userUsername, String receiverName, String receiverPhone, int page, int pageSize) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try {
            OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
            int offset = (page - 1) * pageSize;
            return mapper.selectForAdminByConditionsWithAccount(orderNo, status, merchantUsername, userUsername, receiverName, receiverPhone, offset, pageSize);
        } finally {
            sqlSession.close();
        }
    }
    
    @Override
    public int countOrdersForAdminByConditionsWithAccount(String orderNo, Integer status, String merchantUsername, String userUsername, String receiverName, String receiverPhone) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try {
            OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
            return mapper.countForAdminByConditionsWithAccount(orderNo, status, merchantUsername, userUsername, receiverName, receiverPhone);
        } finally {
            sqlSession.close();
        }
    }
    
    @Override
    public List<Order> getOrderListByMerchantAndStatus(Long merchantId, Integer status, int page, int pageSize) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try {
            OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
            int offset = (page - 1) * pageSize;
            return mapper.selectByMerchantIdAndStatus(merchantId, status, offset, pageSize);
        } finally {
            sqlSession.close();
        }
    }
    
    @Override
    public int countOrdersByMerchantAndStatus(Long merchantId, Integer status) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try {
            OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
            return mapper.countByMerchantIdAndStatus(merchantId, status);
        } finally {
            sqlSession.close();
        }
    }
}






